﻿using System.Security.Claims;
using BlazorPro.BlazorSize;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
using Microsoft.JSInterop;
using MudBlazor.Utilities;
using SageKing.Core.Extensions;
using SageKing.OpenIddict;

using IMessageService = AntDesign.IMessageService;

namespace SageKing.Blazor.OpenIdService.Components.Base;

public class AuthComponentBase : AComponentBase, ITableAutoSize, IAsyncDisposable
{
    public string Token { get; set; }
    public string? currentUrl;
    public bool _hasRedirected = false; // 状态标记

    public string ScrollX { get; set; } = "600";
    public string browserHeightPx { get; set; } = BrowserConsts.browserHeight.ToPx();
    public string browserHeightWithOutTopPx { get; set; } = BrowserConsts.browserHeight.ToPx();

    #region window size
    // windowsize
    public SKWindowSize? windowSize;

    [Inject]
    public ReuseTabsService ReuseTabsService { get; set; }

    [Inject]
    public AuthenticationStateProvider AuthenticationState { get; set; }

    [CascadingParameter]
    public Task<AuthenticationState> AuthStateTask { get; set; }


    [Inject]
    public new ILogger<AuthComponentBase> Logger { get; set; }

    public ClaimsPrincipal User { get; set; }
    public CustomAuthStateProvider AuthStateProvider
    {
        get
        {
            return (CustomAuthStateProvider)AuthenticationState;
        }
    }

    //table height
    #region table auto size

    [Inject]
    public IResizeListener listener { get; set; }
    public Action StateHasChangedAction { get; set; }
    public ITableAutoSize MeTable { get { return this; } }
    [Parameter]
    public string ScrollY { get; set; } = BrowserConsts.ScrollY;
    public string ScrollY1080 { get; set; } = BrowserConsts.ScrollY1080;
    [Parameter]
    public double browserHeight { get; set; } = BrowserConsts.browserHeight;
    public double browserHeight1080 { get; set; } = BrowserConsts.browserHeight1080;
    public double ScrollYOffset { get; set; } = BrowserConsts.ScrollYOffset;
    public bool IsSmallMedia { get; set; } = false;
    // We can also capture the browser's width / height if needed. We hold the value here.
    public BrowserWindowSize browser { get; set; } = new BrowserWindowSize();
    public bool Islarge1080_800 { get; set; } = false;
    public string large1080_800 { get; set; } = BrowserAntDesignConsts.LargeHeight1080_800;
    #endregion

    #endregion


    protected override async Task OnInitializedAsync()
    {
        try
        {
            await base.OnInitializedAsync();

            currentUrl = NavigationManager.Uri;

            StateHasChangedAction = () =>
            {
                UpdateHeightAction();
                UpdateOtherHeightAction();
                StateHasChanged();
            };

            await MeTable.InitTableHeight(true);
            UpdateHeightAction();

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            Logger.LogError(ex, "AuthComponentBase");
        }
    }

    public void UpdateHeightAction()
    {
        ScrollY = $"{browserHeight - ScrollYOffset}px";
        BrowserConsts.ScrollYTable = ScrollY;
        browserHeightPx = browserHeight.ToPx();
        browserHeightWithOutTopPx = (browserHeight - TopOffset).ToPx();
        if (browser != null)
        {
            ScrollX = browser.Width.ToString();
        }
    }
    /// <summary>
    /// 用于子类更新其他参数
    /// </summary>
    public virtual void UpdateOtherHeightAction()
    {

    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            try
            {
                await GetAuthenticationStateAsync();

                var getToken = await AuthStateProvider.AuthService.GetToken();
                if (getToken.IsNullOrEmpty())
                {
                    await AuthStateProvider.SignOut();
                    return;
                }
                Token = getToken;


                // Subscribe to the OnResized event. This will do work when the browser is resized.
                listener.OnResized += MeTable.WindowResized;
                windowSize = await GetSKWindowSize();
                if (windowSize != null)
                {
                    browserHeight = windowSize.pageHeight;
                    UpdateHeightAction();
                    BrowserConsts.WindowSize = windowSize;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                Logger.LogError(ex, "AuthComponentBase");
            }
        }
        else
        {
            await GetSKWindowSize();
        }

        if (BrowserConsts.ScrollYTable != ScrollY)
        {
            UpdateHeightAction();
            StateHasChanged();
        }

    }

    public async Task<SKWindowSize> GetSKWindowSize()
    {
        if (JsCommModule is not null)
        {
            if (IsDisposed)
            {
                return null;
            }

            // 异步等待获取锁。如果锁已被占用，此处不会阻塞线程，而是返回一个Task等待
            await _asyncLock.WaitAsync().ConfigureAwait(false);

            try
            {
                if (IsDisposed)
                {
                    return null;
                }

                windowSize = await JsCommModule.GetWindowSize();
                if (windowSize != null)
                {
                    BrowserConsts.WindowSize = windowSize;
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
                // 无论如何都要释放锁，确保锁最终会被释放，避免死锁
                _asyncLock.Release();
            }
        }
        return null;
    }

    public async Task GetAuthenticationStateAsync()
    {
        if (AuthenticationState == null)
        {
            NavigationManager.NavigateTo(OpenIddictUIConstants.LoginURL);
        }

        var state = await AuthStateProvider.GetAuthenticationStateAsync();

        User = state.User;

        AuthStateProvider.NavigateTo(NavigationManager.Uri, User);

        await Task.Delay(100);
    }

    public ValueTask DisposeAsync()
    {
        IsDisposed = true;
        return ValueTask.CompletedTask;
    }
}
